import asyncio
from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse, StreamingResponse

# 全局缓存最新 JPEG 字节与条件变量（用于通知有新帧）
latest_jpeg = None
frame_condition = asyncio.Condition()

app = FastAPI()

@app.get("/")
async def index():
    html = """
    <html>
    <body>
        <h1>实时视频流 (HTTP)</h1>
        <img src="/video_feed" width="640" height="480">
    </body>
    </html>
    """
    return HTMLResponse(content=html)

async def mjpeg_generator():
    global latest_jpeg
    boundary = b'frame'
    # 首帧前等待，随后每次有新帧都推送
    while True:
        async with frame_condition:
            await frame_condition.wait()
            frame = latest_jpeg
        yield (b'--' + boundary + b"\r\n"
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b"\r\n")

@app.get("/video_feed")
async def video_feed():
    return StreamingResponse(mjpeg_generator(), media_type='multipart/x-mixed-replace; boundary=frame')

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    global latest_jpeg
    await websocket.accept()
    print("摄像头客户端已连接")
    try:
        while True:
            # 期望客户端发送二进制 JPEG 帧
            message = await websocket.receive_bytes()
            async with frame_condition:
                latest_jpeg = message
                frame_condition.notify_all()
    except Exception as e:
        print(f"摄像头客户端断开: {e}")

if __name__ == '__main__':
    import uvicorn
    # 统一在 uvicorn 下运行 ASGI 应用
    uvicorn.run("main:app", host="0.0.0.0", port=8000, ws="websockets", ws_ping_timeout=None)
